/*
 * kary.cn Inc.
 * Copyright (c) 2017 All Rights Reserved.
 * create by kary
 * date:2017-09-09
 */
package com.zerone.pay.merchant.web.controller;

import com.acooly.core.common.dao.support.PageInfo;
import com.acooly.core.common.web.AbstractJQueryEntityController;
import com.acooly.core.common.web.MappingMethod;
import com.acooly.core.common.web.support.JsonListResult;
import com.acooly.core.utils.Dates;
import com.acooly.core.utils.Ids;
import com.acooly.core.utils.Money;
import com.acooly.core.utils.enums.ResultStatus;
import com.acooly.module.security.utils.ShiroUtils;
import com.zerone.facade.merchant.enums.MerchantTypeEnum;
import com.zerone.pay.merchant.repository.entity.MerchantEntity;
import com.zerone.pay.merchant.repository.service.MerchantRepositoryService;
import com.zerone.pay.trade.service.WithdrawServcie;
import com.zerone.pay.trade.service.order.WithdrawOrder;
import com.zerone.payment.account.facade.api.AccountManageFacade;
import com.zerone.payment.account.facade.api.AccountQueryFacade;
import com.zerone.payment.account.facade.api.AccountUnilateralQueryFacade;
import com.zerone.payment.account.facade.info.AccountInfo;
import com.zerone.payment.account.facade.info.QueryUnilateralInfo;
import com.zerone.payment.account.facade.order.CreateAccountOrder;
import com.zerone.payment.account.facade.order.QueryAccountOrder;
import com.zerone.payment.account.facade.order.QueryAccountStatisticsOrder;
import com.zerone.payment.account.facade.order.QueryAccountUnilateralOrder;
import com.zerone.payment.common.exception.PaymentException;
import com.zerone.payment.common.facade.enums.BankCardTypeEnum;
import com.zerone.payment.common.facade.enums.BankCodeEnum;
import com.zerone.payment.common.facade.enums.CertTypeEnum;
import com.zerone.payment.common.facade.enums.PublicTagEnum;
import com.zerone.payment.common.facade.result.PaymentResult;
import com.zerone.payment.common.facade.result.QueryPageResult;
import com.zerone.payment.common.facade.result.QueryResult;
import com.zerone.payment.common.util.MysqlPageUtil;
import com.zerone.payment.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;

/**
 * merchant 管理控制器
 *
 * @author kary Date: 2017-09-09 14:57:58
 */
@Slf4j
@Controller
@RequestMapping(value = "/manage/merchant/merchant")
public class MerchantManagerController	extends AbstractJQueryEntityController<MerchantEntity, MerchantRepositoryService> {
	
	private static final String merchantTag = "merchantTag";
	
	{
		allowMapping = "*";
	}
	
	@Autowired
	private AccountManageFacade accountManageFacade;

	@Autowired
	private AccountQueryFacade accountQueryFacade;

	@Autowired
	private WithdrawServcie withdrawServcie;

	@Autowired
	private AccountUnilateralQueryFacade accountUnilateralQueryFacade;
	
	@Autowired
	private MerchantRepositoryService merchantRepositoryService;
	
	@Override
	protected void referenceData(HttpServletRequest request, Map<String, Object> model) {
		model.put("bankCodes", BankCodeEnum.maps());
		model.put("certTypes", CertTypeEnum.mappingCertType());
		model.put("merchantTypes", MerchantTypeEnum.mappingMerchantType());
		model.put("bankCardTypes", BankCardTypeEnum.mappingBankCardType());
		model.put("publicTags", PublicTagEnum.mappingPublicTag());
	}
	
	@Override
	protected MerchantEntity onSave(HttpServletRequest request, HttpServletResponse response, Model model, MerchantEntity entity, boolean isCreate) throws Exception {
		if (entity.getMerchantType() == MerchantTypeEnum.NORMAL_MERCHANT) {
			MerchantEntity parentMerchant = merchantRepositoryService.findByMerchantId(entity.getParentMerchantId());
			if (parentMerchant == null) {
				throw new PaymentException("普通商户注册,上级商户未注册");
			}
		}
		if (isCreate) {
			entity.setMerchantId(Ids.Did.getInstance().getId(20));
			PaymentResult<AccountInfo> result = accountManageFacade.createAccount(createAccountOrder(entity));
			if (result != null	&& result.getStatus() == ResultStatus.success
				&& result.getDto() != null) {
				entity.setAccountNo(result.getDto().getAccountNo());
			} else {
				throw new PaymentException("资金账户注册失败 " + (result != null ? result.getDetail() : ""));
			}
		}
		return entity;
	}
	

	@RequestMapping({ "agentIndex" })
	public String agentIndex(HttpServletRequest request, HttpServletResponse response, Model model) {
		model.addAttribute(merchantTag, "agent");
		return super.index(request, response, model);
	}
	
	@RequestMapping({ "agentListJson" })
	@ResponseBody
	public JsonListResult<MerchantEntity> agentListJson(HttpServletRequest request, HttpServletResponse response) {
		JsonListResult<MerchantEntity> result = new JsonListResult();
		this.allow(request, response, MappingMethod.list);
		try {
			MerchantEntity entity = findByEmailOrMobile();
			result.appendData(this.referenceData(request));
			Map<String, Object> map = this.getSearchParams(request);
			map.put("LIKE_parentMerchantId", entity.getMerchantId());
			PageInfo<MerchantEntity> pageInfo = merchantRepositoryService.query(this.getPageInfo(request), map, this.getSortMap(request));
			result.setTotal(Long.valueOf(pageInfo.getTotalCount()));
			result.setRows(pageInfo.getPageResults());
		} catch (Exception var5) {
			this.handleException(result, "获取下属商户信息", var5);
		}
		return result;
	}
	
	@RequestMapping({ "agentCreate" })
	public String agentCreate(HttpServletRequest request, HttpServletResponse response, Model model) {
		MerchantEntity entity = findByEmailOrMobile();
		model.addAttribute(merchantTag, "agent");
		model.addAttribute("parentMerchantId", entity.getMerchantId());
		return super.create(request, response, model);
	}
	
	@RequestMapping({ "agentEdit" })
	public String agentEdit(HttpServletRequest request, HttpServletResponse response, Model model) {
		model.addAttribute(merchantTag, "agent");
		return super.edit(request, response, model);
	}
	
	@RequestMapping({ "agentShow", "get" })
	public String agentShow(HttpServletRequest request, HttpServletResponse response, Model model) {
		return super.show(request, response, model);
	}
	
	@RequestMapping({ "normalShow", "get" })
	public String normalShow(HttpServletRequest request, HttpServletResponse response, Model model) {
		return super.show(request, response, model);
	}
	
	@RequestMapping("agentAccount")
	public String agentAccount(HttpServletRequest request, HttpServletResponse response, Model model) {
		try {
			model.addAttribute(merchantTag, "agentAccount");
			MerchantEntity entity = findByEmailOrMobile();
			model.addAttribute("merchant",entity);
			model.addAttribute("accountInfo",queryAccountInfo(entity));
		} catch (Exception var5) {
			log.warn(this.getExceptionMessage("index", var5), var5);
			this.handleException("代理商账户管理", var5, request);
		}

		return this.getAccountView();
	}

	@RequestMapping({ "agentAccountEdit" })
	public String agentAccountEdit(HttpServletRequest request, HttpServletResponse response, Model model) {
		model.addAttribute(merchantTag, "agentAccount");
		return super.edit(request, response, model);
	}


	@RequestMapping("normalAccount")
	public String normalAccount(HttpServletRequest request, HttpServletResponse response, Model model) {
		try {
			model.addAttribute(merchantTag, "normalAccount");
			MerchantEntity entity = findByEmailOrMobile();
			model.addAttribute("merchant",entity);
			model.addAttribute("accountInfo",queryAccountInfo(entity));
		} catch (Exception var5) {
			log.warn(this.getExceptionMessage("index", var5), var5);
			this.handleException("普通商账户管理", var5, request);
		}
		return this.getAccountView();
	}

	@RequestMapping({ "normalAccountEdit" })
	public String normalAccountEdit(HttpServletRequest request, HttpServletResponse response, Model model) {
		model.addAttribute(merchantTag, "normalAccount");
		return super.edit(request, response, model);
	}
	
	@RequestMapping("queryFinanceJson")
	@ResponseBody
	public JsonListResult<QueryUnilateralInfo> queryFinanceJson(HttpServletRequest request, HttpServletResponse response,Model model) {
		JsonListResult<QueryUnilateralInfo> result = new JsonListResult();
		try {
			String startTime = request.getParameter("startTime");
			String endTime = request.getParameter("endTime");
			String merchantId = request.getParameter("merchantId");
			String page = request.getParameter("page");

			Date startDate = StringUtil.isNoneBlank(startTime)? Dates.parse(startTime,Dates.CHINESE_DATE_FORMAT_LINE):null;
			Date endDate = StringUtil.isNoneBlank(endTime)? Dates.parse(startTime,Dates.CHINESE_DATE_FORMAT_LINE):null;
			QueryAccountUnilateralOrder order = createQueryAccountUnilateralOrder(startDate,endDate,page,merchantId);
			QueryPageResult<ArrayList<QueryUnilateralInfo>> queryPageResult = accountUnilateralQueryFacade.queryAccountUnilateral(order);
			if (queryPageResult != null && queryPageResult.getDto() != null){
				PageInfo<QueryUnilateralInfo> pageInfo = new PageInfo<>();
				pageInfo.setPageResults(queryPageResult.getDto());
				pageInfo.setTotalCount(queryPageResult.getTotalCount());
				pageInfo.setCurrentPage((int) queryPageResult.getCurrPage());
				pageInfo.setTotalPage(MysqlPageUtil.calTotalPageNum(queryPageResult.getTotalCount(),10));
				result.setTotal(Long.valueOf(pageInfo.getTotalCount()));
				result.setRows(pageInfo.getPageResults());
			}
		} catch (Exception e) {
			this.handleException(result, "查询账户资金明细", e);
		}
		return result;
	}
	
	@RequestMapping("accountWithdraw")
	public String accountWithdraw(HttpServletRequest request, HttpServletResponse response,Model model) {
		MerchantEntity entity = findMerchant(request.getParameter("id"));
		model.addAttribute("merchant",entity);
		model.addAttribute("accountInfo",queryAccountInfo(entity));
		return getAccountWithdrawView();
	}
	
	@RequestMapping("accountWithdrawJson")
	@ResponseBody
	public JsonListResult<MerchantEntity> accountWithdrawJson(@RequestParam("merchantId")String merchantId,
															  @RequestParam("amount")String amount) {

		JsonListResult<MerchantEntity> result = new JsonListResult();
		try {
			WithdrawOrder order = new WithdrawOrder();
			order.setGid(Ids.gid());
			order.setPartnerId(merchantId);
			order.setMerchantId(merchantId);
			order.setAmount(new Money(amount).getCent());
			order.setOutOrderNo(Ids.Did.getInstance().getId());
			withdrawServcie.withdraw(order);
			result.setMessage("提现成功");
		} catch (Exception e) {
			this.handleException(result, "账户提现", e);
		}
		return result;
	}
	
	private MerchantEntity findByEmailOrMobile() {
		String merchant = ShiroUtils.getCurrentUser().getUsername();
		MerchantEntity entity = merchantRepositoryService.findByEmailOrMobile(merchant, merchant);
		if (entity == null) {
			throw new PaymentException("商户不存在");
		}
		return entity;
	}

	private MerchantEntity findMerchant(String merchantId) {
		MerchantEntity entity = merchantRepositoryService.findByMerchantId(merchantId);
		if (entity == null) {
			throw new PaymentException("商户不存在");
		}
		return entity;
	}

	private AccountInfo queryAccountInfo(MerchantEntity entity){
		QueryResult<AccountInfo> result = accountQueryFacade.queryAccount(createQueryAccountOrder(entity));
		if (result != null && result.success() && result.getDto()!= null){
			return result.getDto();
		}
		throw new PaymentException("获取商户账户信息异常");
	}

	private CreateAccountOrder createAccountOrder(MerchantEntity entity) {
		CreateAccountOrder order = new CreateAccountOrder();
		order.setGid(Ids.gid());
		order.setMemo("创建商户资金账户");
		order.setAccountNo(entity.getMerchantId());
		order.setCustomerId(entity.getMerchantId());
		order.setPartnerId(entity.getMerchantId());
		order.setAccountAlias(entity.getMerchantName());
		return order;
	}

	private QueryAccountOrder createQueryAccountOrder(MerchantEntity entity) {
		QueryAccountOrder order = new QueryAccountOrder();
		order.setGid(Ids.gid());
		order.setMemo("查询商户资金账户");
		order.setAccountNo(entity.getAccountNo());
		order.setPartnerId(entity.getMerchantId());
		return order;
	}

	private QueryAccountUnilateralOrder createQueryAccountUnilateralOrder(Date startTime, Date endTime,String page, String merchantId) {
		QueryAccountUnilateralOrder order = new QueryAccountUnilateralOrder();
		MerchantEntity merchantEntity  = findMerchant(merchantId);
		order.setGid(Ids.gid());
		order.setMemo("查询商户资金流水明细");
		order.setEndTime(endTime);
		order.setStartTime(startTime);
		order.setCurrPage(Integer.valueOf(page));
		order.setAccountNo(merchantEntity.getAccountNo());
		order.setPartnerId(merchantEntity.getMerchantId());
		return order;
	}
	private QueryAccountStatisticsOrder createQueryAccountStatisticsOrder(Date startTime, Date endTime,String merchantId) {
		QueryAccountStatisticsOrder order = new QueryAccountStatisticsOrder();
		MerchantEntity merchantEntity  = findMerchant(merchantId);
		order.setGid(Ids.gid());
		order.setMemo("查询商户资金流水明细");
		order.setEndTime(endTime);
		order.setStartTime(startTime);
		order.setAccountNo(merchantEntity.getAccountNo());
		order.setPartnerId(merchantEntity.getMerchantId());
		return order;
	}

	public String getAccountView() {
		return this.getRequestMapperValue() + "Account";
	}
	
	public String getAccountWithdrawView() {
		return this.getRequestMapperValue() + "AccountWithdraw";
	}
	
}
